package com.example.lotterysystem.service.activitystatus.impl;

import com.example.lotterysystem.common.errorcode.ServiceErrorCodeConstants;
import com.example.lotterysystem.common.exception.ServiceException;
import com.example.lotterysystem.service.ActivityService;
import com.example.lotterysystem.service.activitystatus.ActivityStatusManager;
import com.example.lotterysystem.service.activitystatus.operator.AbstractActivityOperator;
import com.example.lotterysystem.service.dto.ConvertActivityStatusDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

@Component
public class ActivityStatusManagerImpl implements ActivityStatusManager {

    private static final Logger logger = LoggerFactory.getLogger(ActivityStatusManagerImpl.class);

    @Autowired
    private final Map<String, AbstractActivityOperator> operatorMap = new HashMap<>();

    @Autowired
    private ActivityService activityService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void handleEvent(ConvertActivityStatusDTO convertActivityStatusDTO) {

        //1.活动状态的扭转依赖于活动奖品状态的扭转，导致代码维护性差---通过责任链设计模式来解决
        //2.状态扭转条件可能会扩展，当前写法，拓展性差，维护性差 --- 通过策略模式来解决
        if (CollectionUtils.isEmpty(operatorMap)){
            logger.warn("operatorMap为空！");
        }

        //用map来维护奖品，人员或者活动 Map<String,AbstractActivityOperator>
        Map<String,AbstractActivityOperator> currMap = new HashMap<>(operatorMap);
        Boolean update = false;
        //先处理奖品，人员
        update=processConvertStatus(convertActivityStatusDTO,currMap,1);

        //再去处理活动
        update=processConvertStatus(convertActivityStatusDTO,currMap,2) || update;

        //更新缓存
        if (update){
            activityService.cacheActivity(convertActivityStatusDTO.getActivityId());
        }

    }

    @Override
    public void rollbackHandleEvent(ConvertActivityStatusDTO convertActivityStatusDTO) {
        //operator：活动，奖品，人员，这三者都需要回滚
        for (AbstractActivityOperator operator : operatorMap.values()){
            operator.convert(convertActivityStatusDTO);
        }
        //更新缓存
        activityService.cacheActivity(convertActivityStatusDTO.getActivityId());
    }

    private Boolean processConvertStatus(ConvertActivityStatusDTO convertActivityStatusDTO,
                                         Map<String, AbstractActivityOperator> currMap,
                                         int sequence) {
        Boolean update = false;
        // 遍历currMap
        Iterator<Map.Entry<String,AbstractActivityOperator>> iterator = currMap.entrySet().iterator();
        while (iterator.hasNext()){
            AbstractActivityOperator operator = iterator.next().getValue();
            // operator是否需要转换
            if (operator.sequence()!=sequence
                    || !operator.needConvert(convertActivityStatusDTO)){
                continue;
            }
            // 需要转换：转换
            if (!operator.convert(convertActivityStatusDTO)){
                logger.error("{}状态转换失败！",operator.getClass().getName());
                throw new ServiceException(ServiceErrorCodeConstants.ACTIVITY_STATUS_CONVERT_ERROR);
            }
            // 走到这里，状态扭转成功，删除当前operator
            iterator.remove();
            update=true;
        }
        // 返回
        return update;
    }
}
